#ifndef MODBUS_H
#define MODBUS_H

#include "global.h"

#define UART0_BUF_SIZE      128     // 一定是2^n
#define UART0_BUF_MASK      (UART0_BUF_SIZE-1)

extern uchar data uart0_len;                    // uart0已接收/或要发送长度
extern uchar xdata uart0_buf[UART0_BUF_SIZE];   // uart0发送/接收缓冲区
extern ushort data uart0_timestamp;             // 最后接收时间
extern uchar * data uart0_tx_ptr;               // 发送指针
extern bit uart0_rx_pending;                    // uart0正在接收标志
extern bit uart0_tx_pending;                    // uart0正在发送标志
extern bit uart0_delay_process;                 // uart0指令延时处理

#ifdef _USES_UART1
#define UART1_BUF_SIZE      UART0_BUF_SIZE      // 一定是2^n
#define UART1_BUF_MASK      (UART1_BUF_SIZE-1)

extern uchar uart1_tx_len;                      // uart1要发送长度
extern uchar uart1_tx_left;                     // uart1发送剩余长度
extern uchar uart1_rx_len;                      // uart1已接收长度
extern uchar uart1_tx_buf[UART1_BUF_SIZE];      // uart1发送缓冲区
extern uchar uart1_rx_buf[UART1_BUF_SIZE];      // uart1接收缓冲区
extern ushort uart1_timestamp;                  // 最后接收时间
extern uchar * uart1_tx_ptr;                    // 发送指针
extern uchar uart1_retry_times;                 // uart1重试次数
extern uchar uart1_result;                      // uart1通讯结果, 见UART1_RESULT_xxx
extern bit uart1_rx_pending;                    // uart1正在接收标志
extern bit uart1_tx_pending;                    // uart1正在发送标志
extern bit uart1_locked;                        // // uart1访问锁定

// 通讯结果
#define UART1_RESULT_OK                         0
#define UART1_RESULT_TIMEOUT                    1
#define UART1_RESULT_CRC                        2
#define UART1_RESULT_EXCEPTION                  3

#define UART1_START()               uart1_tx_ptr = uart1_tx_buf
#define UART1_APPEND(type, val)     (((type *)uart1_tx_ptr)++[0]) = (val)
#define UART1_END()                 uart1_tx_len = uart1_tx_ptr - uart1_tx_buf

void Uart1_Send();
void Uart1_Read();
void Uart1_Backup();
void Uart1_Restore();

bit Uart1_Exchange_Message();
bit Uart1_Read_RwBit(uchar addr, ushort index, ushort count);
bit Uart1_Read_RoBit(uchar addr, ushort index, ushort count);
bit Uart1_Read_RwWord(uchar addr, ushort index, ushort count);
bit Uart1_Read_RoWord(uchar addr, ushort index, ushort count);
bit Uart1_Read_Event_Count(uchar addr);
void Uart1_Begin_Write_Bit(uchar addr, ushort index,ushort count);
void Uart1_Begin_Write_Word(uchar addr, ushort index, ushort count);

void Modbus_Gateway();
void Modbus_Transparent();

#endif//_USES_UART1

//------------------------------------------
// RO-BIT
//------------------------------------------
extern uchar bdata ro_bit_1;
extern bit x_at_home;                           // x在原点
extern bit y_at_home;                           // Y在原点
extern bit z_at_home;                           // z在原点
extern bit pick_cup_sensor;                     // 抓手已下降到抓杯/放杯位置。1：到位；0：不到位。
extern bit holding_cup;                         // 抓手中有无测试杯状态 1：有； 0：无
extern bit y_at_limit;                          // Y限位状态 1：在限位位置；0：不在限位位置

#define RO_BIT_FIRST        (&ro_bit_1)
#define RO_BIT_COUNT        6

//------------------------------------------
// RW-BIT
//------------------------------------------
extern uchar bdata rw_bit_1;
extern bit elector_manget;                      // 设置抓手电磁铁状态。写入 1 使能电磁铁，打开抓手；写入 0 关闭电磁铁，关闭抓手

#define RW_BIT_FIRST        (&rw_bit_1)
#define RW_BIT_COUNT        1

//------------------------------------------
// RO-WORD
//------------------------------------------
extern long x_pos;              // x当前坐标, step
extern long y_pos;              // Y当前坐标，step
extern long z_pos;              // z当前坐标，step
extern ushort x_duration;       // x运动经过的时间, ms
extern long x_distance;         // x经过的位移
extern ushort y_duration;       // Y运动经过的时间
extern long y_distance;         // Y经过的位移
extern ushort z_duration;       // Z运动经过的时间
extern long z_distance;         // Z经过的位移
extern long z_pick_cup_pos;     // z检测到的抓杯/放杯位置

#define RO_WORD_FIRST       ((ushort*)&x_pos)
#define RO_WORD_COUNT       17

//------------------------------------------
// RW-WORD
//------------------------------------------
extern ushort x_max_speed;              // X最大速度, 0.01 rad/sec^2
extern long x_max_distance;             // X最大行程
extern ushort y_max_speed;              // Y最大速度, 0.01 rad/sec^2
extern long y_max_distance;             // Y最大行程
extern ushort z_max_speed;              // z最大速度，0.01 rad/sec^2
extern long z_max_distance;             // z最大行程
extern ushort reserved1;                // 保留
extern ushort action;                   // 动作指令
extern long x_target;                   // X目标位置
extern long y_target;                   // y目标位置
extern long z_target;                   // z目标位置
extern long flags;                      // 动作标识
extern long x_target_2;                 // X目标坐标2
extern long y_target_2;                 // y目标坐标2
extern long z_target_2;                 // z目标坐标2
extern RECT range;                      // 运行范围
extern RECT block[MAX_BLOCK_COUNT];     // 禁止运行范围


#define RW_WORD_FIRST       (&x_max_speed)
#define RW_WORD_COUNT       0x29

//------------------------------------------
// 文件
//------------------------------------------
#define FILE_COUNT              0
#define MAX_FILE_REQUEST        2       // 一次请求最大的子记录访问数量

#define FILE_BUFFER_SIZE        256
#define FILE_BUFFER_MASK        (FILE_BUFFER_SIZE-1)

extern ushort xdata file_buf[FILE_BUFFER_SIZE];

//------------------------------------------
// 诊断
//------------------------------------------
extern ushort  diagnostic;
extern ushort  bus_message_count;
extern ushort  bus_error_count;
extern ushort  bus_exception_count;
extern ushort  server_message_count;
extern ushort  server_no_response_count;
extern ushort  server_exception_count;
extern ushort  server_busy_count;
extern ushort  bus_char_overrun_count;
extern ushort  server_status;
extern uchar   bdata program_status;

extern bit ps_listen_only;                  // 处于只听模式
extern bit ps_server_busy;                  // 设备忙

// diagnostic寄存器位定义:


//------------------------------------------
// 事件
//------------------------------------------
#define MAX_EVENT_COUNT             64      // 2^n
#define MAX_EVENT_MASK              (MAX_EVENT_COUNT-1)

// 接收事件
#define EVENT_RECEIVED              0x80    // 接收事件
#define EVENT_BROADCAST             0x40    // 接收到广播消息
#define EVENT_LISTEN_ONLY           0x20    // 当前处于只听模式
#define EVENT_CHARRACTER_OVERRUN    0x10    // 字符过载
#define EVENT_COMMUNICATION_ERROR   0x02    // 通讯错误

// 发送事件
#define EVENT_SENT                  0x40    // 发送事件
//#define EVENT_LISTEN_ONLY         0x20    // 当前处于只听模式
#define EVENT_WRITE_TIMEOUT         0x10    // 写超时
#define EVENT_EXCEPTION             0x80    // 异常应答
#define EVENT_BUSY_EXCEPTION        0x04    // 错误代码 5-6
#define EVENT_ABORT_EXCEPTION       0x02    // 错误代码 4
#define EVENT_READ_EXCEPTION        0x01    // 错误代码 1-3

// 进入只听模式事件
#define EVENT_ENTER_LISTEN_ONLY     0x04    // 进入只听模式事件

// 复位事件
#define EVENT_RESET_PORT            0x00    // 复位事件

extern uchar event_count;                   // 事件记数值, event_count索引的event_log为当前事件
extern uchar event_log[MAX_EVENT_COUNT];    // 事件记录

//------------------------------------------
// 异常应答代码
//------------------------------------------
#define ILLEGAL_FUNCTION            0x01
#define ILLEGAL_DATA_ADDRESS        0x02
#define ILLEGAL_DATA_VALUE          0x03
#define SERVER_DEVICE_FAILURE       0x04
#define ACKNOWLEDGE                 0x05
#define SERVER_DEVICE_BUSY          0x06
#define MEMORY_PARITY_ERROR         0x08
#define GATEWAY_PATH_UNAVAILABLE    0x0A
#define GATEWAY_TARGET_NO_RESPONSE  0x0B

//----------------------------------------------------------------------------------
bit Uart0_FrameEnded();
void No_Response();
void Response();
void Exception_Response(uchar err);
void Process_Request();

uchar Read_RO_bit(ushort addr, uchar n);
uchar Read_RW_bit(ushort addr, uchar n);
void Write_bit(ushort addr, uchar val, uchar n);

ushort Read_RO_word(ushort addr);
ushort Read_RW_word(ushort addr);
void Write_word(ushort addr, ushort val);

uchar Read_Exception();
void Diagnose();
void Log_Event(uchar event);

void Read_Identification();

#if FILE_COUNT
// 文件操作
void Reset_File(uchar fid);
void Append_File(uchar fid, ushort *rec, ushort n);
ushort Read_File(uchar fid, ushort addr);
void Write_File(uchar fid, ushort addr, ushort val);
ushort File_Size(uchar fid);
#endif//FILE_COUNT

#endif // MODBUS_H
